﻿using SharpStockLib.DataAccess.CSVMappers;
using SharpStockLib.DataAccess.Persisters;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using SharpStockLib.DataAccess.Providers;
using SharpStockLib.Data;
using System.Data.SQLite;
using System.Reactive.Linq;
using System.Collections.Generic;
using SharpStockLib.Fin;

namespace SharpStockTests
{
    
    
    /// <summary>
    ///This is a test class for SQLitePersisterTest and is intended
    ///to contain all SQLitePersisterTest Unit Tests
    ///</summary>
    [TestClass()]
    public class SQLitePersisterTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///A test for Persist
        ///</summary>
        [TestMethod()]
        public void PersistTest()
        {
            string pathToDB = testContextInstance.TestRunDirectory + "\\test.db";
            SQLitePersister target = new SQLitePersister(pathToDB);

            // Initializes the DB
            if (!target.IsDatabaseValid())
                target.CreateSchema();

            string stockName = "INTC";
            string pathToCSV = testContextInstance.DeploymentDirectory + "\\" + stockName + ".csv";
            target.Persist(pathToCSV, stockName);
            target.Dispose();

            CSVProvider provider = new CSVProvider(pathToCSV, CSVType.YahooHisto);

            CheckValues(provider, stockName, pathToDB);
        }

        /// <summary>
        ///A test for Persist using IObservable
        ///</summary>
        [TestMethod()]
        public void PersistTestAsync()
        {
            string pathToDB = testContextInstance.TestRunDirectory + "\\testAsync.db";
            SQLitePersister target = new SQLitePersister(pathToDB);

            // Initializes the DB
            if (!target.IsDatabaseValid())
                target.CreateSchema();

            string stockName = "INTC";
            string pathToCSV = testContextInstance.DeploymentDirectory + "\\" + stockName + ".csv";
            CSVProvider provider = new CSVProvider(pathToCSV, CSVType.YahooHisto);

            // Persists using IObservable
            target.Persist(provider.GetHistoricalDataAsync(stockName, null, null), stockName);
            target.Dispose();

            CheckValues(provider, stockName, pathToDB);
        }

        private static void CheckValues(CSVProvider provider, string stockName, string pathToDB)
        {
            // Let's check all the values contained in the CSV are in DB
            using (SQLiteConnection connec = new SQLiteConnection("Data Source=" + pathToDB + ";Version=3;Foreign Keys=True;"))
            {
                connec.Open();
                IEnumerable<IData> csvData = provider.GetHistoricalData(stockName, null, null);

                foreach (IData data in csvData)
                {
                    SQLiteCommand cmd = connec.CreateCommand();
                    cmd.CommandText = "SELECT * from eod where symbol='" + stockName + "' and date='" + data.Date.ToString("yyyy-MM-dd") +
                                      "'";
                    using (SQLiteDataReader reader = cmd.ExecuteReader())
                    {
                        // The while loop should be useless, but if we get multiple columns, we will have a problem in the tests unless the primary keys blew off somewhere
                        while (reader.Read())
                        {
                            Assert.AreEqual(data.Date, reader.GetDateTime(1)); // This one should not be a problem, but still
                            Assert.AreEqual(data.Open, reader.GetDouble(2));
                            Assert.AreEqual(data.High, reader.GetDouble(3));
                            Assert.AreEqual(data.Low, reader.GetDouble(4));
                            Assert.AreEqual(data.Close, reader.GetDouble(5));
                            Assert.AreEqual(data.Volume, reader.GetInt32(6));
                        }
                    }
                    cmd.Dispose();
                }

                connec.Close();
            }
        }

        /// <summary>
        ///A test for AreQuotesInDB
        ///</summary>
        [TestMethod()]
        public void AreQuotesInDBTest()
        {
            string pathToDB = testContextInstance.DeploymentDirectory + "\\quotes.db";
            SQLitePersister target = new SQLitePersister(pathToDB);
            const string stockName = "IBM";

            bool result = target.AreQuotesInDB(stockName);
            target.Dispose();

            Assert.IsTrue(result);
        }

        /// <summary>
        ///A test for PersistStock
        ///</summary>
        [TestMethod()]
        public void PersistStockTest()
        {
            string pathToDB = testContextInstance.TestRunDirectory + "\\testStock.db";
            SQLitePersister target = new SQLitePersister(pathToDB);

            // Initializes the DB
            if (!target.IsDatabaseValid())
                target.CreateSchema();

            Stock expected = new Stock("YOUPI");
            expected.Description = "Youpi Corp";
            expected.Sector = SectorNYSE.Industrials.ToString();
            target.PersistStock(expected);
            target.Dispose();

            SQLiteProvider provider = new SQLiteProvider(pathToDB);
            Stock actual = provider.GetStockInfo(expected.Symbol);
            provider.Dispose();

            Assert.AreEqual(expected.Description, actual.Description);
            Assert.AreEqual(expected.Sector, actual.Sector);
        }
    }
}
